// fixbomDlg.cpp : implementation file
//

#include "stdafx.h"
#include "fixbom.h"
#include "fixbomDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFixbomDlg dialog

CFixbomDlg::CFixbomDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFixbomDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CFixbomDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_nTotal = m_nFound = m_nIgnore = 0;
	m_fileignore.AddTail(".svn");
}

void CFixbomDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFixbomDlg)
	DDX_Control(pDX, IDC_LIST1, m_list);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFixbomDlg, CDialog)
	//{{AFX_MSG_MAP(CFixbomDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DROPFILES()
	ON_BN_CLICKED(IDC_BUTTON_FIX, OnButtonFix)
	ON_BN_CLICKED(IDC_BUTTON_EXCLUDE, OnButtonExclude)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFixbomDlg message handlers

BOOL CFixbomDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CFixbomDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CFixbomDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

HCURSOR CFixbomDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CFixbomDlg::OnDropFiles(HDROP hDropInfo) 
{	
	m_nTotal = m_nFound = m_nIgnore = 0;
	m_list.ResetContent();
	m_filelist.RemoveAll();

	TCHAR filePath[1024] = {0};
	TCHAR basePath[1024] = {0};
	UINT uNum = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
	if(uNum)
	{        
		for(UINT i = 0; i < uNum; i++)
		{
			int pathLen = DragQueryFile(hDropInfo, i, filePath, sizeof(filePath));

			if (0 == i) _tcscpy(basePath, filePath);
			else PathCommonPrefix(filePath, CString(basePath), basePath);

			if (FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(filePath))
				SearchDirectory(filePath);
			else
				CheckFile(filePath);
		}
		m_csBasePath = basePath;
	}
	DragFinish(hDropInfo);

	for(POSITION pos = m_filelist.GetHeadPosition(); pos != NULL;)
	{
		TCHAR text[1024] = {0};
		POSITION p = pos;
		CString file = m_filelist.GetNext(pos);
		PathRelativePathTo(text, m_csBasePath, FILE_ATTRIBUTE_DIRECTORY, file, FILE_ATTRIBUTE_NORMAL);

		int n = m_list.AddString(text);
		m_list.SetItemData(n, (DWORD)p);
	}

	CString title;
	title.Format("fixbom --- total: %d, ignore: %d, found: %d", m_nTotal, m_nIgnore, m_nFound);
	SetWindowText(title);

	CDialog::OnDropFiles(hDropInfo);
}

#define BUFF_SIZE 512
void CFixbomDlg::OnButtonFix() 
{
	CStringList el;
	for(POSITION pos = m_filelist.GetHeadPosition(); pos != NULL;)
	{
		CString sf = m_filelist.GetNext(pos);
		try
		{
			CFile fr(sf, CFile::modeRead | CFile::shareDenyNone);
			fr.SeekToBegin();
			int nLen = fr.GetLength();
			CFile fw(sf, CFile::modeWrite | CFile::shareDenyNone);
			fw.SeekToBegin();

			BYTE buff[BUFF_SIZE] = {0};
			int nRead = fr.Read(buff, BUFF_SIZE);
			fw.Write(buff + 3, nRead -3);
			while((nRead = fr.Read(buff, BUFF_SIZE)) > 0){
				fw.Write(buff, nRead);
			}
			fw.SetLength(nLen - 3);
			fw.Flush();
		}
		catch( CFileException* e )
		{
			e;
			el.AddTail(sf);
		}
	}
	if (el.GetCount() > 0){
		CString sText = "Follow files not procced:\n"; 
		for(POSITION pos = el.GetHeadPosition(); pos != NULL;)
			sText += el.GetNext(pos) + "\n";
		AfxMessageBox(sText);
	}

	m_nTotal = m_nFound = m_nIgnore = 0;
	m_list.ResetContent();
	m_filelist.RemoveAll();
}

class CCurDir
{
	CString m_curdir;
public:
	CCurDir(LPCTSTR dir){
		GetCurrentDirectory(1024, m_curdir.GetBuffer(1024));
		m_curdir.ReleaseBuffer();
		SetCurrentDirectory(dir);
	}
	~CCurDir(){
		SetCurrentDirectory(m_curdir);
	}
};

void CFixbomDlg::SearchDirectory(LPCTSTR dir)
{
	CCurDir ccd(dir);

   CFileFind ff;
   BOOL bWorking = ff.FindFile("*.*");
   while (bWorking)
   {
      bWorking = ff.FindNextFile();
      CString csFile = ff.GetFilePath();
	  if (ff.IsDots()) continue;
	  if (ff.IsDirectory()) SearchDirectory(csFile);
	  else CheckFile(csFile);
   }
}

void CFixbomDlg::CheckFile(CString file)
{
	m_nTotal ++;
	
	for(POSITION pos = m_fileignore.GetHeadPosition(); pos != NULL;)
	{
		CString si = m_fileignore.GetNext(pos);
		if (0 == si.CompareNoCase(file.Right(si.GetLength())))	{
			m_nIgnore++; return;
		}
	}

	try{
	CFile f(file, CFile::modeRead);
	BYTE buff[16] = {0};
	f.Read(buff, 10);
	f.Close();
	
	if ((0xEF == buff[0]) && (0xBB == buff[1]) && (0xBF == buff[2])) {
		m_nFound++;
		m_filelist.AddTail(file);
	}
	}catch (CFileException* e){e;}
}

void CFixbomDlg::OnButtonExclude() 
{
	int num = m_list.GetSelCount();
	if (num < 1) return;
	int* pids = new int[num];
	m_list.GetSelItems(num, pids);

	std::list<int> ilist;
	for(int i = 0; i < num; i++)
	{
		//m_list.DeleteString(pids[i]);
		ilist.push_back(pids[i]);
	}
	ilist.sort(); ilist.reverse();
	for(std::list<int>::iterator ii = ilist.begin(); ii != ilist.end(); ii++)
	{
		int id = *ii; 
		POSITION pos = (POSITION) m_list.GetItemData(id);
		m_filelist.RemoveAt(pos);
		m_list.DeleteString(id);
	}
}
